package com.szbmyoubao.app.helper

import com.szbmyoubao.app.http.RetrofitClient
import com.szbmyoubao.app.view.dialog.UploadState
import com.ellecity06.common.utils.logD
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import okio.Buffer
import okio.BufferedSink
import okio.ForwardingSink
import okio.Sink
import okio.buffer
import java.io.File
import java.io.IOException


/**
 * @author zavier
 * @time 2025/3/10 14:45
 * @des
 */
open class ProgressRequestBody(
    private val delegate: RequestBody,
    private val onRequestProgressListener: OnRequestProgressListener?
) : RequestBody() {

    override fun contentType(): MediaType? = delegate.contentType()

    override fun contentLength(): Long {
        try {
            return delegate.contentLength()
        } catch (ioException: IOException) {
            ioException.printStackTrace()
        }
        return -1
    }

    @Throws(IOException::class)
    override fun writeTo(sink: BufferedSink) {
        val countingSink = CountingSink(sink, contentLength(), onRequestProgressListener)
        val bufferedSink = countingSink.buffer()
        delegate.writeTo(bufferedSink)
        bufferedSink.flush()
    }

    protected class CountingSink(delegateSink: Sink, val contentLength: Long, private val onRequestProgressListener: OnRequestProgressListener?) :
        ForwardingSink(delegateSink) {

        private var bytesWritten: Long = 0L

        override fun write(source: Buffer, byteCount: Long) {
            super.write(source, byteCount)
            bytesWritten += byteCount
            onRequestProgressListener?.onRequestProgress(bytesWritten, contentLength)
        }
    }

    interface OnRequestProgressListener {

        fun onRequestProgress(
            bytesWritten: Long,
            contentLength: Long
        )
    }
}

class UploadManager {
    companion object {
        /**
         * 音频文件
         */
        const val TYPE_VOICEO = "voice"

        /**
         * 视频文件
         */
        const val TYPE_VIDEO = "video"

        /**
         * 图片文件
         */
        const val TYPE_IMAGE = "image"

        /**
         * 背景图
         */
        const val TYPE_BG = "bg"

        /**
         * 背景音乐
         */
        const val TYPE_BGM = "bgm"
        suspend fun uploadVideo(filepath: String) = upload(TYPE_VIDEO, filepath)
        suspend fun uploadImage(filepath: String) = upload(TYPE_IMAGE, filepath)
        suspend fun uploadAudio(filepath: String) = upload(TYPE_VOICEO, filepath)

        suspend fun upload(type: String, filepath: String): Flow<UploadState> {
            logD("上传文件=type=$type,,filepath=$filepath")

            return flow {
                val fileRequestBody = ProgressRequestBody(
                    File(filepath).asRequestBody("multipart/form-data".toMediaType()),
                    object : ProgressRequestBody.OnRequestProgressListener {
                        override fun onRequestProgress(bytesWritten: Long, contentLength: Long) {
//                            emit(UploadState.InProgress(bytesWritten))
                            logD(
                                "junit",
                                "onRequestProgress: bytesWritten->$bytesWritten," + "contentLength->$contentLength,progress->${bytesWritten.times(1.0f) / contentLength}"
                            )

                        }
                    }
                )
                logD("文件名字=${File(filepath).name}")
                val requestBody = MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .apply {
                        addFormDataPart("type", type)
                        addFormDataPart(
                            "file",
                            File(filepath).name,
                            fileRequestBody
                        )
                    }.build()
                val response = RetrofitClient.service2.uploadFiles(requestBody)
                if (response.isSuccess) {
                    logD("result=$response")
                    emit(UploadState.Success(response.data!!))

                } else {
                    logD("result222=$response")
                    emit(UploadState.Error(IOException(response.toString())))
                }
            }.catch {
                logD("上传错误=$it")
                emit(UploadState.Error(it))
            }.flowOn(Dispatchers.IO)

        }
    }
}